#!/bin/bash
set -e


######################## 需要自定义修改的参数 ###################################
# 安装hosts,若为single，仅需传入单个IP，若为多个则以英文逗号隔开
HOSTS="192.168.66.161,192.168.66.162,192.168.66.163"
# 绝对路径
ZK_INSTALL_DIR=/app
# 绝对路径
JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el7_9.x86_64
# 这边只要名称
ZK_PKG_NAME=apache-zookeeper-3.6.3-bin.tar.gz
ZK_CLIENT_PORT=2181
##############################################################################

# 以下参数不用修改
ZK_INSTALL_TYPE=$1   # 传入 single/cluster
ZK_MYID_NUM=$2 		 # 传入值1/2/3，single模式仅传入1即可
ZK_UNPKG_NAME=`echo ${ZK_PKG_NAME%%.tar*}`
ZK_BASE_DIR=$ZK_INSTALL_DIR/zookeeper

## 打印
print_message(){
  TAG=$1
  MSG=$2
  if [[ $1 = "Error" ]];then
    echo -e "`date +'%F %T'` [\033[31m$TAG\033[0m] $MSG"
  elif [[ $1 = "Warning" ]];then
    echo -e "`date +'%F %T'` [\033[34m$TAG\033[0m] $MSG"
  else
    echo -e "`date +'%F %T'` [\033[32m$TAG\033[0m] $MSG"
  fi
}

## 参数预检查
check_params(){
	print_message "Note" "检查基础参数是否已设置..."
	if [ ! "$HOSTS" ] || [ ! "$ZK_INSTALL_DIR" ] || [ ! "$JAVA_HOME" ] || [ ! "$ZK_PKG_NAME" ] || [ ! "$ZK_CLIENT_PORT" ];then
    print_message "Error" "传入参数不全，请检查"
    exit
  fi
}

## 检查是否已安装 JDK8
check_jdk(){
  print_message "Note" "检查是否已安装jdk..."
  JAVA_STATUS=`rpm -qa|grep java-1.8|wc -l`
  if [ $JAVA_STATUS -gt 0 ];then
    print_message "Note" "jdk已安装..."
  else
  	print_message "Error" "请先安装 JDK..."
  	exit
  fi
}

# 检查是否已安装zk
zk_is_running(){
	print_message "Note" "检查是否已存在运行的ZK..."
	ZK_CNT=`ps -ef | grep  Dzookeeper|grep -v grep|wc -l`
	if [ $ZK_CNT -gt 0 ];then
		print_message "Error" "已存在运行的ZK，请检查..."
		exit 1
	fi	
}

## 检查安装路径
check_zk_path(){
	print_message "Note" "检查ZK安装路径是否存在：$ZK_INSTALL_DIR"
	if [ ! -d $ZK_INSTALL_DIR ];then
	  print_message "Note" "创建安装路径：$ZK_INSTALL_DIR"
      mkdir -p $ZK_INSTALL_DIR
    else
      print_message "Note" "安装路径已存在：$ZK_INSTALL_DIR"
	fi
}

check_data_isempty(){
  print_message "Note" "检查ZK数据目录是否为空..."
  if [ -d $ZK_BASE_DIR/data ];then
    if [ "$(ls -A $ZK_BASE_DIR/data)" ];then
      print_message "Error" "目录$ZK_BASE_DIR/data 已存在且不为空"
      exit 1
    else
      print_message "Warning" "目录$ZK_BASE_DIR/data 已存在"
    fi
  fi
}

## 设置zk配置文件
set_zk_config(){
	print_message "Note" "配置Zookeeper参数文件..."
	IP_ARRAYS=(${HOSTS//,/ })

	if [[ $ZK_INSTALL_TYPE = "single" ]] && [[ ${#IP_ARRAYS[@]} -eq 1 ]];then
		cat > $ZK_BASE_DIR/conf/zoo.cfg << EOF
tickTime=2000
initLimit=1000
syncLimit=10
dataDir=$ZK_BASE_DIR/data
dataLogDir=$ZK_BASE_DIR/logs
clientPort=$ZK_CLIENT_PORT
maxClientCnxns=500
autopurge.snapRetainCount=10
autopurge.purgeInterval=1
globalOutstandingLimit=100
preALLocSize=131072
snapCount=1000000
server.1= ${IP_ARRAYS[0]}:2888:3888
EOF
	elif [[ $ZK_INSTALL_TYPE = "cluster" ]] && [[ ${#IP_ARRAYS[@]} -eq 3 ]];then
		cat > $ZK_BASE_DIR/conf/zoo.cfg << EOF
tickTime=2000
initLimit=1000
syncLimit=10
dataDir=$ZK_BASE_DIR/data
dataLogDir=$ZK_BASE_DIR/logs
clientPort=$ZK_CLIENT_PORT
maxClientCnxns=500
autopurge.snapRetainCount=10
autopurge.purgeInterval=1
globalOutstandingLimit=100
preALLocSize=131072
snapCount=1000000
server.1= ${IP_ARRAYS[0]}:2888:3888
server.2= ${IP_ARRAYS[1]}:2888:3888
server.3= ${IP_ARRAYS[2]}:2888:3888
EOF
	else
		print_message "Error" "配置Zookeeper参数文件失败，请传入正确的IP地址：$IP_ARRAYS..."
		exit 1
	fi
}

set_zk_systemd(){
	print_message "Note" "配置Zookeeper systemd启动"
	cat > /lib/systemd/system/zookeeper.service << EOF
[Unit]
Description=ZooKeeper Service
After=network.target

[Service]

Type=forking
Environment=JAVA_HOME=$JAVA_HOME
ExecStart=$ZK_BASE_DIR/bin/zkServer.sh start
ExecReload=$ZK_BASE_DIR/bin/zkServer.sh restart  
ExecStop=$ZK_BASE_DIR/bin/zkServer.sh stop 
Restart=always
[Install] 

WantedBy=default.target
EOF
}

install_zookeeper(){
	print_message "Note" "开始安装Zookeeper"

	zk_is_running
	check_jdk
	check_zk_path

	if [ -d $ZK_INSTALL_DIR/$ZK_UNPKG_NAME ];then
	  print_message "Warning" "目录 $ZK_INSTALL_DIR/$ZK_UNPKG_NAME 已存在..."
	else
	  print_message "Note" "解压Zookeeper..."
	  tar zxf ./soft/$ZK_PKG_NAME -C $ZK_INSTALL_DIR
	fi

	if [ -d $ZK_BASE_DIR ];then
	  print_message "Warning" "目录 $ZK_BASE_DIR 已存在..."
	else
	  print_message "Note" "文件名更改为zookeeper..."
	  mv $ZK_INSTALL_DIR/$ZK_UNPKG_NAME $ZK_BASE_DIR
	fi

	check_data_isempty
	print_message "Note" "创建zookeeper数据目录和日志目录..."
	mkdir -p $ZK_BASE_DIR/{data,logs}

	set_zk_config

    print_message "Note" "添加myid文件"
    echo "${ZK_MYID_NUM}"> $ZK_BASE_DIR/data/myid

    set_zk_systemd

    print_message "Note" "重载unit配置文件"
	systemctl daemon-reload
	print_message "Note" "使用systemctl命令启动zookeeper"
	systemctl start zookeeper

	ZK_STATUS=`systemctl status zookeeper.service |grep "active (running)"|wc -l`
  if [ $ZK_STATUS -gt 0 ];then
    print_message "Note" "安装完成，Zookeeper已启动...   可使用 systemctl status zookeeper.service 进行查看状态 "
  else
    print_message "Error" "启动判断异常，请查看错误日志！"
    exit
  fi

	print_message "Note" "将zookeeper服务加入开机启动项"
	systemctl enable zookeeper    
	print_message "Note" "Zookeeper安装完成"
}

check_params

if  [ "$1" = "single" ] && [ $2 -eq 1 ];then
  print_message "Note" "当前模式为单节点部署..."
  install_zookeeper
elif  [ "$1" = "cluster" ];then
	if [ $2 = "1" ] || [ $2 = "2" ] || [ $2 = "3" ];then
  	  print_message "Note" "当前模式为集群部署，当前部署节点$ZK_MYID_NUM ..."	
  	  install_zookeeper
  	else
      print_message "Error" "请传入正确的值!"
  	fi
else
  printf "Usage: bash install_zookeeper.sh {single|cluster} {1|2|3}\n"
  printf "for example: 安装单节点版 ./install_zookeeper.sh single 1\n             安装集群版本，分别在各服务器执行：./install_zookeeper.sh cluster 1|2|3\n"
  exit
fi



